<template>
  <div style="width: 100%">
    <div ref="mirroEditorRef" style="border: 1px solid #ccc; border-radius: 4px; min-width: 50px; width: 100%"></div>
  </div>
</template>

<script setup name="Command" lang="ts">
import { javascript } from "@codemirror/lang-javascript";
import { basicSetup, EditorView } from "codemirror";
import { autocompletion } from "@codemirror/autocomplete";
import { EditorState } from "@codemirror/state";
// import {EditorView} from "@codemirror/view"
import { onMounted, Ref, ref, watch } from "vue";
const emit = defineEmits(["update:modelValue"]);
let props = defineProps({
  grammers: {
    type: Array,
    required: false,
    default: () => {
      return [];
    }
  },
  modelValue: {
    type: String,
    required: false,
    default: ""
  }
});
const allKeyList: Ref<{ label: string; type: string; apply: string; detail: string }[]> = ref([]);

// 获取自定义提示内容
function getCommandList() {
  allKeyList.value = [
    { label: "@match", type: "keyword", apply: "match", detail: "match" },
    { label: "@hello", type: "variable", apply: "hello", detail: "hellodetail" },
    { label: "@magic", type: "text", apply: "⠁⭒*.✩.*⭒⠁", detail: "macro" }
  ];
}
getCommandList();
let editor: any = null;
const mirroEditorRef: Ref<Element | DocumentFragment | undefined> = ref();
let myTheme = EditorView.theme(
  {
    "&": {
      color: "#000",
      backgroundColor: "#fff"
    },
    ".cm-content": {
      caretColor: "#000"
    },
    ".cm-activeLine": {
      backgroundColor: "#fff"
    },
    "&.cm-focused .cm-cursor": {
      borderLeftColor: "#000"
    },
    "&.cm-focused .cm-selectionBackground, ::selection": {
      backgroundColor: "#fff"
    },
    ".cm-gutters": {
      backgroundColor: "#fff",
      color: "#ddd",
      border: "none",
      display: "none"
    }
  },
  { dark: false }
);

// 初始化编辑器
function initCodeContent() {
  if (!editor) {
    let state = EditorState.create({
      doc: "hello!!!", //这是文本
      extensions: [
        basicSetup,
        javascript(),
        myTheme,
        autocompletion({ override: [myCompletions] }),
        EditorView.updateListener.of(function (e) {
          if (e.docChanged) {
            emit("update:modelValue", e.state.doc.toString());
          }
        })
      ]
    });
    editor = new EditorView({
      parent: mirroEditorRef.value,
      state: state
    });
  }
  editor.dispatch({
    changes: {
      from: 0,
      to: editor.state.doc.length,
      insert: props.modelValue
    }
  });
}

// 自定义的代码不全，options为自定义内容，以@开头进行匹配
function myCompletions(context: any) {
  let word: {
    from: number;
    text: string;
    to: number;
  } = {
    from: 0,
    text: "",
    to: 0
  };

  let list: { label: string; type: string; apply: string }[] = [];
  if (context.pos == 0 && !context.explicit) {
    return null;
  } else if (context.matchBefore(/\$\{\w*/)) {
    word = context.matchBefore(/\$\{\w*/);
    word.from = word.from + 2;
    word.to = word.to + 2;
    list = props.grammers
      .filter((item: any) => !item.method && item.function && item.function.startsWith(word.text.replace("${", "")))
      .map((item: any) => {
        return { label: item.function, type: "keyword", apply: item.function, info: item.comment };
      });
  } else if (context.matchBefore(/\.\w*/)) {
    word = context.matchBefore(/\.\w*/);
    word.from = word.from + 1;
    word.to = word.to + 1;
    const wordW = context.matchBefore(/\w*\.\w*/);
    const words = wordW.text.split(".");
    const listT = props.grammers
      .filter((item: any) => item.method && item.method.startsWith(words[1]) && (words[0].endsWith(item.function) || !item.function))
      .map((item: any) => {
        return item;
      });
    let dataInfo: any = {};
    listT.forEach((item: any, index: number) => {
      let { method, info } = item;
      if (!dataInfo[method]) {
        dataInfo[method] = {
          label: method,
          type: "text",
          apply: method,
          info: `所属类：${item.owner}\n> 描述：${item.comment}\n案例：${item.example}`
        };
      }
      dataInfo[method].info += `\n> 所属类：${item.owner}\n 描述：${item.comment}\n案例：${item.example}`;
    });
    list = Object.values(dataInfo); // list 转换成功的数据
  } else {
    return null;
  }
  return {
    from: word.from ? word.from : context.pos,
    options: list
  };
}

watch(
  () => props.modelValue,
  (New) => {
    if (New !== editor.state.doc.toString()) {
      editor.dispatch({
        changes: {
          from: 0,
          to: editor.state.doc.length,
          insert: New
        }
      });
    }
  }
);

onMounted(() => {
  initCodeContent();
});
</script>

<style scoped>
#coder {
  margin-top: 10px;
  width: 100%;
}
.cm-activeLine {
  background-color: #fff !important;
}
</style>
